#include "Object.h"

MessageHandler* Object::messageHandler = NULL;
unsigned long Object::nextID = 0;

std::map<ID,MessageHeader*> Object::messageMap = std::map<ID,MessageHeader*>();

ControlMessage* Object::createControlMessage()
{
	ControlMessage* message = new ControlMessage(nextID++);
	messageMap.insert(std::make_pair(message->_id, message));

	return message;
}

PlayerMessage* Object::createPlayerMessage(unsigned long machineID)
{
	PlayerMessage* message = new PlayerMessage(nextID++);
	message->machineID = machineID;
	messageMap.insert(std::make_pair(message->_id, message));

	return message;
}

ItemMessage* Object::createItemMessage()
{
	ItemMessage* message = new ItemMessage(nextID++);
	messageMap.insert(std::make_pair(message->_id, message));

	return message;
}

void Object::init(bool listening) 
{
	Network::init(listening);
	std::stringstream localHost;
	localHost << Network::getLocalEndpoint();
	ID::machineID = RSHash(localHost.str()); 
}

unsigned long Object::RSHash(std::string const &str)
{
	unsigned int b = 378551;
	unsigned int a = 63689;
	unsigned int hash = 0;

	for (unsigned int i = 0; i < str.length(); i++)
	{	
		hash *= a;
		hash += str[i];
		a *= b;
	}

	return hash;
}

void Object::onReceiveMessage(MessageHeader *receivedMessage)
{
	ID id = receivedMessage->_id;
	MessageHeader *messageCopy = messageMap[id];
	if (messageCopy == NULL)
	{
		switch (receivedMessage->_type)
		{
			case CONTROL:
				messageCopy = new ControlMessage(id);
				break;
			case PLAYER:
				messageCopy = new PlayerMessage(id);
				break;
			case ITEM:
				messageCopy = new ItemMessage(id);
				break;
			default:
				// unknown message type
				return;
		}

		messageMap[id] = messageCopy;
	}

	//update message
	switch (receivedMessage->_type)
	{
		case CONTROL:
			*(ControlMessage *)messageCopy = *(ControlMessage *)receivedMessage;
			break;
		case PLAYER:
			*(PlayerMessage *)messageCopy = *(PlayerMessage *)receivedMessage;
			break;
		case ITEM:
			*(ItemMessage *)messageCopy = *(ItemMessage *)receivedMessage;
			break;
		default:
			// unknown message type
			return;
	}
}

void Object::handleMessage(ID id,boost::asio::ip::udp::endpoint senderEndpoint)
{
	if (messageHandler)
	{
		MessageHeader *message = messageMap[id];
		switch (message->_type)
		{
			case CONTROL:
				messageHandler->onReceiveControlMessage((ControlMessage *)message, senderEndpoint);
				break;
			case PLAYER:
				messageHandler->onReceivePlayerMessage((PlayerMessage *)message, senderEndpoint);
				break;
			case ITEM:
				messageHandler->onReceiveItemMessage((ItemMessage *)message, senderEndpoint);
				break;
			default:
				// unknown message type
				return;
		}
	}
}

void Object::setMessageHandler(MessageHandler *messageHandler) 
{
	Object::messageHandler = messageHandler;
}

void Object::sendMessage(MessageHeader *changedMessage)
{
	Network::sendMessage(changedMessage);
}

void Object::sendMessageNow(MessageHeader *changedMessage)
{
	Network::sendMessageNow(changedMessage);
}

void Object::receiveMessage()
{
	Network::receiveMessage();
}

void Object::startReceiving()
{
	Network::startReceiving();
}

void Object::stopReceiving()
{
	Network::stopReceiving();
}

std::map<ID, MessageHeader*>::const_iterator Object::getMessageMapBegin() 
{
	return messageMap.begin();
}

std::map<ID, MessageHeader*>::const_iterator Object::getMessageMapEnd() 
{
	return messageMap.end();
}
unsigned long Object::getMachineID()
{
	return ID::machineID;
}